# 配置 SWC

[SWC](https://github.com/swc-project/swc)（Speedy Web Compiler）是基于 Rust 语言编写的高性能 JavaScript 和 TypeScript 转译和压缩工具。SWC 提供与 Babel 和 Terser 相似的能力，在单线程上它比 Babel 快 20 倍，在四核上它比 Babel 快 70 倍。

Rsbuild 默认启用 SWC 的以下功能：

- 通过 Rspack 的 [builtin:swc-loader](https://rspack.dev/guide/features/builtin-swc-loader) 来转换 JavaScript 和 TypeScript 代码，它是 [swc-loader](https://github.com/swc-project/pkgs/tree/main/packages/swc-loader) 的 Rust 版本。
- 通过 Rspack 的 [SwcJsMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/swc-js-minimizer-rspack-plugin) 来压缩 JavaScript 代码。

## Loader 选项

`builtin:swc-loader` 的选项与 JS 版本的 swc-loader 一致。Rsbuild 提供了 [tools.swc](/config/tools/swc) 选项来配置 `builtin:swc-loader`，下面是一些示例：

### 注册 SWC 插件

`tools.swc` 可以用于注册 SWC 的 Wasm 插件，比如注册 [@swc/plugin-styled-components](https://www.npmjs.com/package/@swc/plugin-styled-components)：

```js
export default {
  tools: {
    swc: {
      jsc: {
        experimental: {
          plugins: [['@swc/plugin-styled-components', {}]],
        },
      },
    },
  },
};
```

> 你可以通过 [awesome-swc](https://github.com/swc-contrib/awesome-swc) 仓库查看社区中可用的 SWC 插件。

### SWC 插件版本

请注意，SWC 的插件仍然是一个实验性功能，目前 SWC 的 Wasm 插件是不向后兼容的，SWC 插件的版本与 Rspack 依赖的 `swc_core` 版本存在强耦合关系。

这意味着，你需要选择和当前 `swc_core` 版本匹配的 SWC 插件，才能使它正常执行。如果你使用的 SWC 插件版本与 Rspack 依赖的 `swc_core` 版本不匹配，Rspack 在执行构建时会抛出如下错误：

```text
1: failed to run Wasm plugin transform. Please ensure the version of `swc_core`
   used by the plugin is compatible with the host runtime.
```

如果你遇到了以上问题，通常可行的解决方法是将 Rsbuild 和 SWC 插件都升级到最新版本。

此外，你也可以按照以下步骤来选择合适的 SWC 插件版本：

1. 查看当前使用的 Rspack 版本，你可以通过 [调试模式](/guide/debug/debug-mode) 来查看。
2. 访问 [plugins.swc.rs](https://plugins.swc.rs/)，选择你当前使用的 Rspack 版本。
3. 该网站会列出你当前使用的 Rspack 版本所匹配的 SWC 插件版本范围，选择匹配的 SWC 插件版本使用即可。

如果你使用的 SWC 插件未收录到 [plugins.swc.rs](https://plugins.swc.rs/)，可以通过 Rust 代码仓库中的 Cargo.toml 文件来查看 `swc_core` 的版本信息。以 Rspack 仓库为例，你可以打开 [Cargo.toml](https://github.com/web-infra-dev/rspack/blob/main/Cargo.toml)，搜索 `swc_core` 关键字来查看版本，然后参考 [SWC - Selecting the version](https://swc.rs/docs/plugin/selecting-swc-core) 进行选择。

### 启用 Emotion 支持

启用 `builtin:swc-loader` 对 Emotion 支持的示例：

```js
export default {
  tools: {
    swc: {
      jsc: {
        experimental: {
          plugins: [['@swc/plugin-emotion', {}]],
        },
      },
    },
  },
};
```

更多选项可参考 [@swc/plugin-emotion](https://www.npmjs.com/package/@swc/plugin-emotion)。

### 启用 Relay 支持

启用 `builtin:swc-loader` 对 Relay 支持的示例：

```js
export default {
  tools: {
    swc: {
      jsc: {
        experimental: {
          plugins: [['@swc/plugin-relay', {}]],
        },
      },
    },
  },
};
```

更多选项可参考 [@swc/plugin-relay](https://www.npmjs.com/package/@swc/plugin-relay)。

## Minimizer 选项

Rsbuild 提供了 [output.minify.js](/config/output/minify) 选项来配置 SwcJsMinimizerRspackPlugin，下面是一些示例：

### 排除文件

通过 `exclude` 选项可以排除某些文件，不进行压缩：

```ts
export default {
  output: {
    minify: {
      jsOptions: {
        exclude: /foo\/bar/,
      },
    },
  },
};
```

## 切换压缩工具

如果 SwcJsMinimizerRspackPlugin 无法满足你的需求，你可以通过 [tools.bundlerChain](/config/tools/bundler-chain) 选项来切换到其他压缩工具。

例如，切换到 [Terser](https://github.com/webpack-contrib/terser-webpack-plugin) 来压缩 JavaScript 代码，它的性能不如 SWC，但功能更稳定：

```ts
export default {
  tools: {
    bundlerChain(chain, { CHAIN_ID, isProd }) {
      if (isProd) {
        chain.optimization.minimizer(CHAIN_ID.MINIMIZER.JS).use(TerserPlugin, [
          {
            minify: TerserPlugin.terserMinify,
          },
        ]);
      }
    },
  },
};
```
